import { FactoryTaskHelper } from "GameLoop/WorldState/EntityManager/Entitys/room/factory/FactoryTaskHelper";
import { BASE_PRODUCE } from "GameLoop/WorldState/EntityManager/Entitys/room/factory/constants";
import { object } from "lodash";
import { cache_key_arg0, cache_return } from "utils/decorate/decorate";

 
interface RoomResource 
{
    roomName:string;
    count:number;
}
 
enum ResourceState
{
    /**
     * 未满
     */
     Shortage,
    /**
     * 已满
     */
     Excess,
}

export class  ResourceCache
{
    cache:Record<ResourceState,Record<ResourceConstant,RoomResource[]>
    >={[ResourceState.Excess]:{},
    [ResourceState.Shortage]:{}} as any;
    public addRecord(state:ResourceState,minerial:ResourceConstant,arg:RoomResource)
    {
        if( this.cache[state][minerial])
        {
            const index = this.cache[state][minerial].findIndex(e=>e.roomName == arg.roomName);
            if(index>-1)
            {
                this.cache[state][minerial][index].count =arg.count;
                return
            }
            this.cache[state][minerial].push(arg);
        }
        else
        {
            this.cache[state][minerial] = [arg];
        }
    }

    public  removeRecord(state:ResourceState,minerial:ResourceConstant,roomName:string,amount?:number)
    {
        if(   this.cache[state][minerial])
        {
            const val = this.cache[state][minerial];
            const index = _.findIndex(val,e=>e.roomName == roomName);
            if(index>-1)
            {
                if(amount)
                {
                    this.cache[state][minerial][index].count-=amount;
                    if(this.cache[state][minerial][index].count<=0)
                    {
                        this.cache[state][minerial].splice(index,1);
                    }
                }
                else
                {
                    this.cache[state][minerial].splice(index,1);
                }
                
            }
        }
    }

    public getSurplusResource(state:ResourceState,minerial:ResourceConstant)
    {
        if(this.cache[state][minerial])
        {
            return _.sum(this.cache[state][minerial],e=>e.count);
        }
        return 0
    }

   
}
 
export class GlobalResource
{
    private cache!:ResourceCache
    constructor()
    {
        this.cache = new ResourceCache()
    //    this.MarketData.PriceEquation =  global.MemAlloc.GetMemory(["MarketData"]);
    }
    // @cache_return("cache_rooms",1)
    public get myrooms():string[]
    {
        return Object.keys(global.entityDB.Entities)
        // return []
    }
    public resetCahce()
    {
        this.cache.cache={[ResourceState.Excess]:{},
        [ResourceState.Shortage]:{}} as any;
    }
    
    public getUseCapacity(resourceType:ResourceConstant):number
    {
        let cache_key = 'cache_count'+resourceType;
        if((Game as any)[cache_key] === undefined)
        {
            let sum=0;
            for(const item of this.myrooms)
            {
                const coreentity  = Game.rooms[item].getEntity("CoreEntity");
                sum+=coreentity.resourceCount(resourceType);
            }
            (Game as any)[cache_key] =sum;
            return sum;
        }
        return (Game as any)[cache_key] 
    }
    @cache_return("cache",0)
    public getResourceDB ():Record<ResourceConstant,DBItem>
    {
        const dbitem :Record<ResourceConstant,DBItem>={} as any;
    
        {
            const suplus = this.cache.cache[1];
            const keys = suplus ? Object.keys(suplus) as ResourceConstant[] : [];
            for(const e of keys )
            {
                if(!dbitem[e] )
                {
                    dbitem[e]={surplus:{},shortage:{}}
                }
                suplus[e].forEach(f=>{
                    dbitem[e].surplus[f.roomName]=f.count;
                })
            }
        }
        
        {
            const shortage = this.cache.cache[0];

            const keys = shortage ? Object.keys(shortage) as ResourceConstant[] : [];
            for(const e of keys )
            {
                if(!dbitem[e] )
                {
                    dbitem[e]={surplus:{},shortage:{}}
                }
                shortage[e].forEach(f=>{
                    dbitem[e].shortage[f.roomName]=f.count;
                })
            }
        }
        Memory.Debug["cachetime"] =Game.time;
        Memory.Debug["cache"] = JSON.parse(JSON.stringify(this.cache.cache));
        return dbitem
    }
     
  
    public getShortage()
    {
        return this.cache.cache[0]
    }

    /**
     * 注册房间多余资源记录
    */
     public registerExcessResource(room: Room, resource: ResourceConstant, amount: number): void {
        // Add the excess resource record to the cache
        if(amount>0)
        {
            this.cache.addRecord(ResourceState.Excess,resource, { roomName: room.name, count: amount });
        }
        
    }

    /**
     * 注册房间短缺资源记录
    */
    public registerShortageResource(room: Room, resource: ResourceConstant, amount: number): void {
        // Add the shortage resource record to the cache
        if(amount>0)
        {
            this.cache.addRecord(ResourceState.Shortage,resource, { roomName: room.name, count: amount });
        }
    }

    public removeShortageResource(room: Room, resource: ResourceConstant, amount?: number): void {
        
        this.cache.removeRecord(ResourceState.Shortage,resource,room.name)
    }
    /**
     * 对富裕资源进行减少，当少于0则删除
     * @param room 
     * @param resource 
     * @param amount 
     */
    public subtractSurplusResource(room: Room, resource: ResourceConstant, amount: number): void {
        
        this.cache.removeRecord(ResourceState.Excess,resource,room.name,amount)
    }
    public getSurplusResource(resourceType:ResourceConstant)
    {
        return this.cache.getSurplusResource(ResourceState.Excess,resourceType)
    }

    /**
     * 判断全局资源是否能够足够生产
     * @param target 
     * @param time 
     * @returns 
     */
    public isCanbeProduce( target:CommodityConstant,amount:number):boolean
    {
        const time = Math.ceil( amount/COMMODITIES[target].amount);
        const targetamount = COMMODITIES[target].amount*time;
        //const submap:Record<string,number>={};
        const subconstants = COMMODITIES[target].components;
        for(const subconstant in  subconstants)
        {
            // 1.需要op 工厂生产的
            if(COMMODITIES[subconstant as CommodityConstant].level)
            {
                // 除去普通商品之外的需要等级生产的商品
                //if(!NormalProduct.has(subconstant as CommodityConstant))
                {
                    // bflag = true;
                    const amount = FactoryTaskHelper.ClacSubResourceAmount(target as CommodityConstant,targetamount,subconstant as FactoryResourceType);
                    //submap[subconstant]=amount;
                    if(this.getUseCapacity(subconstant as ResourceConstant)<amount  )
                    {
                        return false;
                    }
                }
            }
            else
            {
                if(BASE_PRODUCE[subconstant])
                {
                    const amount = FactoryTaskHelper.ClacSubResourceAmount(target as CommodityConstant,targetamount,subconstant as FactoryResourceType);
                    if(this.getSurplusResource(subconstant as ResourceConstant)<amount  )
                    {
                        return false;
                    }

                }
            }
            // 2.不需要op工厂生产的
        }
        return true
    }
}
